AWS Lambdaのログまわりに関すること まとめ
はじめに
最近、AWS Lambdaの勉強をしているのですがログまわりの機能が非常に便利だと感じました。私がAWS Lambdaのログ周りで調査した内容をまとめます。 Lambda使いたいけどCloudWatchあまり使ったことない方にぜひ読んでもらいたいです。言語は私はPythonとNode.jsを使えないのでJavaで試しています。
ロギングライブラリに関して
まずはロギングライブラリに関してです。 Javaに関する話になっていしまいますが、LambdaLoggerかlog4jを利用することでCloudWatchログに書き込むことが可能です。CloudWatchであれば過去ログの検索が簡単できたり、特定の文字列を含むログが出力された場合に通知することができるためかなり便利です。バックアップを自分で作成する必要もありません。
CloudWatchに書き込んだログを確認する
まずはLambdaLoggerを使ったログ出力のサンプルを作って試してみます。以下のLambda Functionを実行してみましょう。
package s3sample; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.S3Event; public class SampleLambdaFunction implements RequestHandler<S3Event, Object> { @Override public Object handleRequest(S3Event input, Context context) { context.getLogger().log("Input: " + input); // TODO: implement your handler return null; } }
Lambdaのロールに以下のポリシーを適用すると、CloudWatchにログ出力できるようになります。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": [ "arn:aws:logs:*:*:*" ] } ] }
実行したらログが出力されているかを確認します。Management ConsoleのCloudWatchの画面で左のメニューにあるログを選択します。
実行したLambda Functionと同じ名前のロググループがあるのでクリックします。次にログストリームの一覧が表示されますが、時間が一番新しいログストリームを選択してください。以下のように出力したログが表示されていると思います(2行目)。時間とキーワードで検索できます。キーワードはスペースで区切って複数指定できます。
log4jの導入手順
log4jはログレベル(DEBUG、INFO、WARN、ERROR、FATAL)を分けやすいのとlog4j.propertiesで自由にフォーマットを変えられるのでお勧めです。クラス名やソースコードの行数なども出力できます。CloudWatchログで検索する際にログレベルやクラス名を検索できますので便利ではないかと思います。
以下は2行目がlog4jで3行目をLambdaLoggerで出力しています。ログにクラス名と行数が表示されているのが分かります。
LambdaからLog4jを使ってCloudWatchログに出力するためには、log4のjarファイルとLambdaAppenderクラスを含んだjarファイルをダウンロードしクラスパスを通します。次に設定ファイルであるlog4j.propertiesを作成し、クラスパスが通っている場所に置いておきます。以下はLog4jでログ出力するサンプルソースになります。
Apache log4j 1.2 - Maven Repository: com.amazonaws » aws-lambda-java-log4j » 1.0.0
import org.apache.log4j.Logger; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.S3Event; public class LambdaLogSample implements RequestHandler<S3Event, Object> { static final Logger logger = Logger.getLogger(LambdaLogSample.class); @Override public Object handleRequest(S3Event input, Context context) { logger.debug("log4j logger"); return null; } }
以下はlog4j.propertiesのサンプルになります。
log = . log4j.rootLogger = DEBUG, LAMBDA #Define the LAMBDA appender log4j.appender.LAMBDA=com.amazonaws.services.lambda.runtime.log4j.LambdaAppender log4j.appender.LAMBDA.layout=org.apache.log4j.PatternLayout log4j.appender.LAMBDA.layout.conversionPattern=%d{yyyy-MM-dd HH:mm:ss} <%X{AWSRequestId}> %-5p %c{1}:%L - %m%n
以下のドキュメントを参考にしています。 ロギング(Java) - AWS Lambda
ログの保持期間に関して
ログの保持期間はデフォルトは無期限になっています。有効期限を設定する場合はCloudWatchの以下の画面で「失効しない」リンクをクリックすると設定画面が表示されます。保持期間を選択してOKボタンをクリックして下さい。
CloudWatchのログ監視に関して
CloudWatchログの監視機能を使えばログを監視して、特定の文字列が含まれるログが出力した場合にAmazon SNSで通知することができます。メトリックスフィルタ列の0フィルタというリンクをクリックします。
ここで監視する文字列を指定します。実際に出力されているログを使ってどの程度一致するかを確認ことができます。 この例ではExeptionという文字列が含まれていた場合に通知するようにしました。
例外発生時の通知
Lambda Function内でcatchされない例外が発生した場合にCloudWatchのアラームに表示するようにできます。Amazon SNSを使ってメールなどで通知することも可能です。詳細はCloudWatchログにも出力されていますのでそちらを確認する必要があります。
Management ConsoleのCloudWatchの画面を開きます。左側のメニューからアラームを選択し、アラームを作成ボタンをクリックします。
検索窓にLambdaファンクション名と"Errors"という文字列を入力しメトリックスをフィルタリングします。
表示されたメトリックスにチェックを入れ、次へボタンをクリックします。
次にアラームの定義をします。以下のようにエラー(Errors)>=1 が1回連続した場合にアラームを発生させるようにします。 通知する場合はSNSの設定が必要がです。
アラームの作成は以上になります。わざと例外を発生させてメールが送信されるのを確認してみてください。 例外が発生してしまった場合は自動的にリトライしてくれるようです。回数などはサービスによって違います。
最後に
調べたことは以上になります。Lambdaから出力したログはManagement Console上で管理できメール送信の設定も簡単で驚きました。 個人的にはlog4j使えるのが嬉しかったです。CloudWatchあまり使ったことない方はぜひ試してみてください。